package org.wsocket.config;

import java.io.File;
import java.net.URL;

import org.apache.log4j.Logger;
import org.wsocket.Exception.WSocketException;
import org.wsocket.utils.StringUtil;

public class WSocketLoader {
	private static Logger log = Logger.getLogger(WSocketLoader.class);

	private final static int SOCKETSETSIZE_DEFAULT = 5;
	private final static int[] PORTS_DEFAULT = { 8888, 8889 };
	private final static int SOCKETTIMEOUT_DEFAULT = 5 * 60 * 1000;
	private static final int THREAD_POOL_SIZE_DEFAULT = 5;

	private final static String prop_socketSetSize = "socketSetSize";
	private final static String prop_ports = "ports";
	private final static String prop_SocketTimeOut = "socketTimeOut";
	private final static String prop_thread_pool_size = "threadPoolSize";

	private final static String regex = ",";
	private final static String CONFIGFILENAME = "WSocket.properties";

	private static WSocketConfigCacheFile configCacheFile = null;

	private static Config config = new Config();

	/**
	 * read config file and write properties into Config object
	 */
	static {
		init();
	}

	/**
	 * read config file and write properties into Config object also used for
	 * refresh config file
	 * 
	 */
	public static void init() {
		config = initDefault();
		URL lURL = Thread.currentThread().getContextClassLoader().getResource(
				CONFIGFILENAME);
		if (lURL != null) {
			try {
				configCacheFile = new WSocketConfigCacheFile(new File(lURL
						.toURI()));
				config = initConfig(config);
			} catch (Exception ex) {
				log
						.debug("Configuration file:"
								+ lURL.toString()
								+ " file invalid or not found. Use default config now.......");
			}
		} else {
			log
					.debug("Configuration file invalid or not found. Use default config now.......");
		}
	}

	private static Config initDefault() {
		if (log.isDebugEnabled()) {
			log.debug("Initializing default config...");
		}
		Config config = new Config();
		config.setPorts(PORTS_DEFAULT);
		config.setSocketSetSize(SOCKETSETSIZE_DEFAULT);
		config.setSocketTimeOut(SOCKETTIMEOUT_DEFAULT);
		config.setThreadPoolSize(THREAD_POOL_SIZE_DEFAULT);
		return config;
	}

	private static Config initConfig(Config config) throws WSocketException {
		if (log.isDebugEnabled()) {
			log.debug("Initializing config...");
		}
		try {
			if (!StringUtil.isEmpty(getConfigValue(prop_ports))) {
				int[] ports = StringUtil.fromStringToIntArray(
						getConfigValue(prop_ports), regex);
				config.setPorts(ports);
			}
			if (!StringUtil.isEmpty(getConfigValue(prop_socketSetSize))) {
				config.setSocketSetSize(Integer
						.parseInt(getConfigValue(prop_socketSetSize)));
			}
			if (!StringUtil.isEmpty(getConfigValue(prop_SocketTimeOut))) {
				config.setSocketTimeOut(Integer
						.parseInt(getConfigValue(prop_SocketTimeOut)));
			}
			if (!StringUtil.isEmpty(getConfigValue(prop_thread_pool_size))) {
				config.setThreadPoolSize(Integer
						.parseInt(getConfigValue(prop_thread_pool_size)));
			}
		} catch (NumberFormatException e) {
			throw new WSocketException("NumberFormatException", e);
		}
		return config;
	}

	/**
	 * Get the config document from the config manager.
	 * 
	 * @param name
	 *            The name of the configuration attribute
	 * @return The Config DOM.
	 * @throws WSocketException
	 *             if failed to get the document from the Config Mgr.
	 */
	private static String getConfigValue(String name) throws WSocketException {
		String value = "";
		try {
			value = configCacheFile.getValue(name).trim();
		} catch (WSocketException e) {
			log.error("Error accessing Config Mgr " + " name " + name, e);
			throw new WSocketException("config error", e);
		}
		return value;
	}

	/**
	 * @return the config
	 */
	public static Config getConfig() {
		return config;
	}
}
